
/***************************/
/** ENTREPRENEUR - CHOICE **/
/***************************/


// --> either JD or EJ no need to save JD or EJ. But save if default, so that you know next time transition !!
double focE(const double xval, void * params){
    
    struct paramsgolden *focparams= (struct paramsgolden *) params;
    
    // Values and relevant policy functions in R and B //
    double *valueBnextfoc   =   focparams->valueBnextST;
    double *valueRnextfoc   =   focparams->valueRnextST;
#if OPT_compute_C_flow == 1
    double *C_Bnextfoc      =   focparams->C_BnextST;
    double *C_Rnextfoc      =   focparams->C_RnextST;
#endif
    double *saveBnext       =   focparams->saveBnextST;
    double *saveRnext       =   focparams->saveRnextST;
    double *searchBnext     =   focparams->searchBnextST;
    double *searchRnext     =   focparams->searchRnextST;
    
#if SEA == 1
    double *valueBinextfoc  =   focparams->valueBinextST;
    double *valueRinextfoc  =   focparams->valueRinextST;
#if OPT_compute_C_flow == 1
    double *C_Binextfoc     =   focparams->C_BinextST;
    double *C_Rinextfoc     =   focparams->C_RinextST;
#endif
    double *saveBinext      =   focparams->saveBinextST;
    double *saveRinext      =   focparams->saveRinextST;
    double *searchBinext    =   focparams->searchBinextST;
    double *searchRinext    =   focparams->searchRinextST;
#endif
    
    // state space //
    int tgridfoc=focparams->tgridST; int igridfoc=focparams->igridST; int zgridfoc=focparams->zgridST;
    int Jinsured=focparams->JinsuredST; // used for SEA
    // to check
    int iter=focparams->iterST; // iteration number in the VFI loop.
    int method=focparams->methodST; // method used
    
    int indicator, condition, penalty, zz, ixgridB, ixgridR;
    double LHS_B, LHS_R, probadefault, COHR, COHB, saveB, saveR, searchB, searchR;
    double xgridB, xgridR, dxgridB, dxgridR, valueB, valueR, C_B, C_R, RHS, valfoc, profit_temp, profitR, profitE_tmp, muENDO, weight,profit_neg_temp, tempE, C_tempE;
    double optival[maxfirmtype], optisave[maxfirmtype], optidefault[maxfirmtype], optisearch[maxfirmtype];  // for each zz you need to save the behavior.
    
    // indicator if borrower -- IF BORROWER, THEN HAVE TO LOOP OVER r(Phi) //
    if(xval > grid[igridfoc]){indicator = 1;}else{indicator=0;}
    
    // GUESS AN INTEREST RATE //
    double RATEendo = 1.0 + rstar + wedgerate;
    
    // set first proba to 0, without penalty //
    probadefault = 0.0; condition = 1;  penalty = 0;
    
    // case borrow.
    if(indicator == 1){
        while(condition == 1){
            
            // bank condition first guess //
            LHS_B = 0.0; LHS_R = 0.0; probadefault = 0.0; penalty = 0; tempE = 0.0; C_tempE = 0.0;
            
            for(zz = 0; zz<maxfirmtype; zz++){
                
                COHB    = findCOH_B(igridfoc, zz, tgridfoc, xval, RATEendo, Jinsured);
                xgridB  = invexpspace(COHB,GridminCOH,GridmaxCOH,EchelleCOH,maxgridCOH);
                dxgridB = weightinter(COHB, xgridB, &ixgridB, gridCOH, maxgridCOH);
                //if ((ixgridB>=(maxgridCOH-1))){printf("focE: ixgrid>=(maxgrid-1) %d\n",ixgridB);getchar();}
                //if ((COHB<(0.0))){printf("focE: (COHB_1<(0.0)) %20.15f\n",COHB);getchar();}
                
                
                COHR    = max(0.0,findCOH_R(igridfoc, zz, tgridfoc, xval, RATEendo, Jinsured));
                xgridR  = invexpspace(COHR,GridminCOH,GridmaxCOH,EchelleCOH,maxgridCOH);
                dxgridR = weightinter(COHR, xgridR, &ixgridR, gridCOH, maxgridCOH);
                //if ((ixgridR>=(maxgridCOH-1))){printf("focE: ixgrid>=(maxgrid-1) %d\n",ixgridR);getchar();}
                
                
                // COMPUTE THE INDUCED POLICIES -- normal case.
                if(Jinsured == 0){
                    valueB  = inter1d(dxgridB,valueBnextfoc[inxRB((ixgridB),tgridfoc,zz)],valueBnextfoc[inxRB((ixgridB+1),tgridfoc,zz)]);
#if OPT_compute_C_flow == 1
                    C_B     = inter1d(dxgridB,C_Bnextfoc[inxRB((ixgridB),tgridfoc,zz)],C_Bnextfoc[inxRB((ixgridB+1),tgridfoc,zz)]);
#endif
                    saveB   = inter1d(dxgridB,saveBnext[inxRB((ixgridB),tgridfoc,zz)],saveBnext[inxRB((ixgridB+1),tgridfoc,zz)]);
                    searchB = inter1d(dxgridB,searchBnext[inxRB((ixgridB),tgridfoc,zz)],searchBnext[inxRB((ixgridB+1),tgridfoc,zz)]);
                    
                    valueR  = inter1d(dxgridR,valueRnextfoc[inxRB((ixgridR),tgridfoc,zz)],valueRnextfoc[inxRB((ixgridR+1),tgridfoc,zz)]);
#if OPT_compute_C_flow == 1
                    C_R     = inter1d(dxgridR,C_Rnextfoc[inxRB((ixgridR),tgridfoc,zz)],C_Rnextfoc[inxRB((ixgridR+1),tgridfoc,zz)]);
#endif
                    saveR   = inter1d(dxgridR,saveRnext[inxRB((ixgridR),tgridfoc,zz)],saveRnext[inxRB((ixgridR+1),tgridfoc,zz)]);
                    searchR = inter1d(dxgridR,searchRnext[inxRB((ixgridR),tgridfoc,zz)],searchRnext[inxRB((ixgridR+1),tgridfoc,zz)]);
                }
                
                
#if SEA == 1
                // here the insurance status next period is going to depend on the current probability, and this the profit.
                // it is possible that we cannot do a simple loop over RATEendo...
                if(Jinsured == 1){
                    
                    muENDO  = muendoSEA(0.0,tgridfoc);
                    // muENDO = min(max(0.0,mupar*(bstarcostfun(0.0,tgridfoc)/((1.0-taxrate)*rhostar*wstar*prod[tgridfoc]))),mupar);
                    //if(muENDO > mupar+0.00000001 || muENDO < 0){printf("MISTAKE muENDO");getchar();}
                    
                    // in case of bankrupt, recover the full insurance -- so get uninsured with probability mupar.
                    valueB = muENDO*inter1d(dxgridB,valueBnextfoc[inxRB((ixgridB),tgridfoc,zz)],valueBnextfoc[inxRB((ixgridB+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridB,valueBinextfoc[inxRB((ixgridB),tgridfoc,zz)],valueBinextfoc[inxRB((ixgridB+1),tgridfoc,zz)]));
#if OPT_compute_C_flow == 1
                    C_B    = muENDO*inter1d(dxgridB,C_Bnextfoc[inxRB((ixgridB),tgridfoc,zz)],C_Bnextfoc[inxRB((ixgridB+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridB,C_Binextfoc[inxRB((ixgridB),tgridfoc,zz)],C_Binextfoc[inxRB((ixgridB+1),tgridfoc,zz)]));
#endif
                    saveB = muENDO*inter1d(dxgridB,saveBnext[inxRB((ixgridB),tgridfoc,zz)],saveBnext[inxRB((ixgridB+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridB,saveBinext[inxRB((ixgridB),tgridfoc,zz)],saveBinext[inxRB((ixgridB+1),tgridfoc,zz)]));
                    searchB = muENDO*inter1d(dxgridB,searchBnext[inxRB((ixgridB),tgridfoc,zz)],searchBnext[inxRB((ixgridB+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridB,searchBinext[inxRB((ixgridB),tgridfoc,zz)],searchBinext[inxRB((ixgridB+1),tgridfoc,zz)]));
                    
                    
                    profitR = profitRfun(igridfoc, zz, tgridfoc, xval, RATEendo);
                    muENDO  = muendoSEA(profitR,tgridfoc);
                    //muENDO  = min(max(0.0,mupar*(bstarcostfun(profitR,tgridfoc)/((1.0-taxrate)*rhostar*wstar*prod[tgridfoc]))),mupar);
                    //if(muENDO > mupar+0.00000001 || muENDO < 0){printf("MISTAKE muENDO");getchar();}
                    
                    // in case of bankrupt, do not recover the full insurance -- so get uninsured with lower probability.
                    valueR = muENDO*inter1d(dxgridR,valueRnextfoc[inxRB((ixgridR),tgridfoc,zz)],valueRnextfoc[inxRB((ixgridR+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridR,valueRinextfoc[inxRB((ixgridR),tgridfoc,zz)],valueRinextfoc[inxRB((ixgridR+1),tgridfoc,zz)]));
#if OPT_compute_C_flow == 1
                    C_R    = muENDO*inter1d(dxgridR,C_Rnextfoc[inxRB((ixgridR),tgridfoc,zz)],C_Rnextfoc[inxRB((ixgridR+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridR,C_Rinextfoc[inxRB((ixgridR),tgridfoc,zz)],C_Rinextfoc[inxRB((ixgridR+1),tgridfoc,zz)]));
#endif
                    saveR = muENDO*inter1d(dxgridR,saveRnext[inxRB((ixgridR),tgridfoc,zz)],saveRnext[inxRB((ixgridR+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridR,saveRinext[inxRB((ixgridR),tgridfoc,zz)],saveRinext[inxRB((ixgridR+1),tgridfoc,zz)]));
                    searchR = muENDO*inter1d(dxgridR,searchRnext[inxRB((ixgridR),tgridfoc,zz)],searchRnext[inxRB((ixgridR+1),tgridfoc,zz)])+
                    (1.0-muENDO)*(inter1d(dxgridR,searchRinext[inxRB((ixgridR),tgridfoc,zz)],searchRinext[inxRB((ixgridR+1),tgridfoc,zz)]));
                }
#endif
                
                // case bankrupt.
                if((valueB > valueR) || findCOH_R(igridfoc, zz, tgridfoc, xval, RATEendo, Jinsured) < 0.0){
                    
                    // Compute the value of the bank in case of default //
                    profitE_tmp = profitE(statez[zz],tgridfoc,xval);
                    profit_temp     = max(profitE_tmp,0.0);
                    profit_neg_temp = min(profitE_tmp,0.0);
                    // the first min is to ensure that the bankruptcy == value repayment in case of no default (cannot recover more than what it gave)
                    //LHS_B += mzprob[zgridfoc][zz]*min(RATEendo*(xval - grid[igridfoc]),min(frac_repay*(xval-grid[igridfoc]) + profit_temp,(1 - court_cost)*xval + profit_neg_temp) + profit_temp);
                    //LHS_B += mzprob[zgridfoc][zz]*min(RATEendo*(xval - grid[igridfoc]),min(frac_repay*(xval-grid[igridfoc]) + profit_temp,(1 - court_cost)*xval + profit_temp));
                    LHS_B += mzprob[zgridfoc][zz]*min(RATEendo*(xval - grid[igridfoc]),min(frac_repay*(xval-grid[igridfoc]),(1 - court_cost)*xval + profit_neg_temp) + profit_temp);
                    
                    probadefault += mzprob[zgridfoc][zz];
                    
                    // save the values associated to this state //
                    optival[zz] = valueB;   optisave[zz] = saveB;   optisearch[zz] = searchB;    optidefault[zz] = 1.0;
                    tempE   += mzprob[zgridfoc][zz]*valueB;
                    C_tempE += mzprob[zgridfoc][zz]*C_B;
                    
                } else {
                    
                    // Compute the value of the bank in case of repayment BECAREFUL RATENDO IS PUT AFTER. //
                    LHS_R += mzprob[zgridfoc][zz]*(xval - grid[igridfoc]);
                    
                    // save the values associated to this state //
                    optival[zz] = valueR;   optisave[zz] = saveR;   optisearch[zz] = searchR;     optidefault[zz] = 0.0;
                    tempE   += mzprob[zgridfoc][zz]*valueR;
                    C_tempE += mzprob[zgridfoc][zz]*C_R;
                }
                
                
                //                if(zgridfoc == 4 & igridfoc == 2 & tgridfoc == 0){
                //                    printf("CHECK :: %f %f | %d %d %d %d : %f %f | %f %f | %f %f %f ", xval, RATEendo, zz, zgridfoc,igridfoc,tgridfoc,COHR,COHB, valueB, valueR, optival[zz], tempE, probadefault);getchar();
                //                }
            } // end zz
            
            
            // CHECK IF THE EQUATION OF THE BANK HOLDS //
            // compute the left-hand side, that is how much the entrepreneur has to pay back to household + cost //
            RHS = (xval-grid[igridfoc])*(1.0+rstar+wedgerate);
            
            // can borrow the amount considered (case repayment always for instance).
            if((LHS_B + LHS_R*(RATEendo)) >= RHS-0.00000001){condition = 0;}
            
            // can not borrow the amount considered at the price considered.
            if((LHS_B + LHS_R*(RATEendo)) < RHS-0.00000001){
                
                // 1st case: always bankrupt -- impossible to let the entrepreneur borrow. Apply a penalty as compared to the case where entrepreneur invest all his wealth
                if(probadefault >= 0.99){penalty = 1;    RATEendo = 9999;   condition = 0;}
                
                // 2nd case: proba bankrupt < 1 -- solve the new interest rate which makes the bank formula holds and loop again.
                if((probadefault) < 0.99){
                    RATEendo  =(((1.0+rstar+wedgerate)*(xval - grid[igridfoc]) - LHS_B)/LHS_R+0.000001)*(1-relaxRate) + relaxRate*RATEendo;
                    condition = 1;
                }
            } // end if on bank
            
            //            if(zgridfoc == 4 & igridfoc == 2 & tgridfoc == 0){
            //                printf("CHECK :: %f %f | %d %d %d %d : %f %f | %f %f | %f %f %f | bank = %f %f %f ", xval, RATEendo, zz, zgridfoc,igridfoc,tgridfoc,COHR,COHB, valueB, valueR, optival[zz], tempE, probadefault, LHS_B, LHS_R, RHS);getchar();
            //            }
            
            
        } // end while
        
    } else { // end condition on a borrower -- case not borrowing.
        
        C_tempE = 0.0;
        tempE   = 0.0;
        penalty = 0.0;
        
        for(zz = 0; zz < maxfirmtype; zz++){
            
            COHR    = findCOH_R(igridfoc, zz, tgridfoc, xval, RATEendo, Jinsured); // COH repayment RATEendo is useless here.
            xgridR  = invexpspace(COHR,GridminCOH,GridmaxCOH,EchelleCOH,maxgridCOH);
            dxgridR = weightinter(COHR, xgridR, &ixgridR, gridCOH, maxgridCOH);
            //if ((ixgridR>=(maxgridCOH-1))){printf("focE: ixgrid>=(maxgrid-1) %d\n",ixgridR);getchar();}
            //if ((COHR<(0.0))){printf("focE: (COHR_3<(0.0)) %20.15f\n",COHR);getchar();}
            
            // COMPUTE THE INDUCED POLICIES //
            if(Jinsured == 0){
                valueR  = inter1d(dxgridR,valueRnextfoc[inxRB((ixgridR),tgridfoc,zz)],valueRnextfoc[inxRB((ixgridR+1),tgridfoc,zz)]);
#if OPT_compute_C_flow == 1
                C_R     = inter1d(dxgridR,C_Rnextfoc[inxRB((ixgridR),tgridfoc,zz)],C_Rnextfoc[inxRB((ixgridR+1),tgridfoc,zz)]);
#endif
                saveR   = inter1d(dxgridR,saveRnext[inxRB((ixgridR),tgridfoc,zz)],saveRnext[inxRB((ixgridR+1),tgridfoc,zz)]);
                searchR = inter1d(dxgridR,searchRnext[inxRB((ixgridR),tgridfoc,zz)],searchRnext[inxRB((ixgridR+1),tgridfoc,zz)]);
            }
            
#if SEA == 1
            if(Jinsured == 1){
                
                profitR = profitRfun(igridfoc, zz, tgridfoc, xval, RATEendo);
                muENDO  = muendoSEA(profitR,tgridfoc);
                //muENDO  = min(max(0.0,mupar*(bstarcostfun(profitR,tgridfoc)/((1.0-taxrate)*rhostar*wstar*prod[tgridfoc]))),mupar);
                //if(muENDO > mupar+0.00000001 || muENDO < 0){printf("MISTAKE muENDO");getchar();}
                
                valueR = muENDO*inter1d(dxgridR,valueRnextfoc[inxRB((ixgridR),tgridfoc,zz)],valueRnextfoc[inxRB((ixgridR+1),tgridfoc,zz)])+
                (1.0-muENDO)*(inter1d(dxgridR,valueRinextfoc[inxRB((ixgridR),tgridfoc,zz)],valueRinextfoc[inxRB((ixgridR+1),tgridfoc,zz)]));
#if OPT_compute_C_flow == 1
                C_R    = muENDO*inter1d(dxgridR,C_Rnextfoc[inxRB((ixgridR),tgridfoc,zz)],C_Rnextfoc[inxRB((ixgridR+1),tgridfoc,zz)])+
                (1.0-muENDO)*(inter1d(dxgridR,C_Rinextfoc[inxRB((ixgridR),tgridfoc,zz)],C_Rinextfoc[inxRB((ixgridR+1),tgridfoc,zz)]));
#endif
                saveR = muENDO*inter1d(dxgridR,saveRnext[inxRB((ixgridR),tgridfoc,zz)],saveRnext[inxRB((ixgridR+1),tgridfoc,zz)])+
                (1.0-muENDO)*(inter1d(dxgridR,saveRinext[inxRB((ixgridR),tgridfoc,zz)],saveRinext[inxRB((ixgridR+1),tgridfoc,zz)]));
                searchR = muENDO*inter1d(dxgridR,searchRnext[inxRB((ixgridR),tgridfoc,zz)],searchRnext[inxRB((ixgridR+1),tgridfoc,zz)])+
                (1.0-muENDO)*(inter1d(dxgridR,searchRinext[inxRB((ixgridR),tgridfoc,zz)],searchRinext[inxRB((ixgridR+1),tgridfoc,zz)]));
                
            }
#endif
            
            optival[zz]     = valueR;
            optisave[zz]    = saveR;
            optisearch[zz]  = searchR;
            optidefault[zz] = 0.0;
            tempE   += mzprob[zgridfoc][zz]*valueR;
#if OPT_compute_C_flow == 1
            C_tempE += mzprob[zgridfoc][zz]*C_R;
#endif
            
        } // end for zz
    } // end condition on a saver
    
    
    // pass the optimal behavior in function of zz
    focparams->JNE_save     = optisave;
    focparams->JNE_search   = optisearch;
    focparams->JNE_default  = optidefault;
    focparams->JNE_val      = optival;
    focparams->rate_endo    = RATEendo;
    
    // make the value of borrowing worse off than no borrowing if penalty == 1, so will choose not to borrow.
    if(penalty == 1){
        valfoc           = 10000;
        focparams->C_val = -10000;
    }else{
        valfoc           = -tempE;
        focparams->C_val = C_tempE;
    }
    
    
    
    
    
    return valfoc;
}

